﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;


namespace ZipUp
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            try
            {
                var zipfile = args[0];
                var files = new List<string>();
                for (int i = 1; i < args.Length; i++)
                {
                    if (args[i].ToLower().StartsWith("[dir]"))
                    {
                        var dirfile = args[i].ToLower().Replace("[dir]", "");
                        var file = Path.Combine(Environment.CurrentDirectory, dirfile);
                        if (!Directory.Exists(file))
                        {
                            throw new DirectoryNotFoundException(dirfile);
                        }
                        files.Add("[dir]" + file);
                    }
                    else
                    {
                        var file = Path.Combine(Environment.CurrentDirectory, args[i]);
                        if (!File.Exists(file))
                        {
                            throw new FileNotFoundException(file);
                        }
                        files.Add(file);
                    }
                }
                Program.ZipFiles(zipfile, files.ToArray());
            }
            catch (Exception ex)
            {
                Console.WriteLine(((object)ex).ToString());
                Environment.Exit(1);
            }
        }

        private static void ZipFiles(string destination, string[] files)
        {

            using (Package package = Package.Open(destination, FileMode.Create))
            {
                foreach (var file in files)
                {
                    if (file.ToLower().StartsWith("[dir]"))
                    {
                        var dirfile = file.ToLower().Replace("[dir]", "");
                        foreach (FileInfo fileInfo in new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, dirfile)).GetFiles())
                        {

                            Uri partUri = PackUriHelper.CreatePartUri(new Uri(fileInfo.Directory.Name +  "\\"  + fileInfo.Name, UriKind.Relative));
                            PackagePart part = package.CreatePart(partUri, "application/octet-stream");
                            using (FileStream fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                            {
                                CopyStream((Stream)fileStream, part.GetStream());
                                Console.WriteLine(dirfile + "\\" + fileInfo.Name + " added to " + destination);
                            }
                        }
                    }
                    else
                    {
                        var fi = new FileInfo(file);
                        Uri partUrifile = PackUriHelper.CreatePartUri(
                                                        new Uri(fi.Name, UriKind.Relative));
                        // Add the Document part to the Package
                        PackagePart packagePartDocument =
                            package.CreatePart(partUrifile, "application/octet-stream");
                        // Copy the data to the Document Part
                        using (FileStream fileStream = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            CopyStream(fileStream, packagePartDocument.GetStream());
                            Console.WriteLine(fi.Name + " added to " + destination);
                        }
                    }

                }
            }
        }

        // Create the Package
        // (If the package file already exists, FileMode.Create will
        //  automatically delete it first before creating a new one.
        //  The 'using' statement insures that 'package' is
        //  closed and disposed when it goes out of scope.)
        public static void Compress(string zipfile, FileInfo fi)
        {
            Uri partUrifile = PackUriHelper.CreatePartUri(
                                      new Uri(fi.Name, UriKind.Relative));
            using (Package package = Package.Open(zipfile, FileMode.Create))
            {
                // Add the Document part to the Package
                PackagePart packagePartDocument =
                    package.CreatePart(partUrifile, "application/octet-stream");
                // Copy the data to the Document Part
                using (FileStream fileStream = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    CopyStream(fileStream, packagePartDocument.GetStream());
                }
            }
        }
        /// <summary>
        ///   Copies data from a source stream to a target stream.</summary>
        /// <param name="source">
        ///   The source stream to copy from.</param>
        /// <param name="target">
        ///   The destination stream to copy to.</param>
        private static void CopyStream(Stream source, Stream target)
        {
            const int bufSize = 0x1000;
            byte[] buf = new byte[bufSize];
            int bytesRead = 0;
            while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
                target.Write(buf, 0, bytesRead);
        }
    }
}
